package cn.zch.soft.util.qrcode.utils.qartutil;
import com.google.zxing.common.BitMatrix;
import org.apache.log4j.PropertyConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Properties;
/**
 * Hello world!
 */
public class QArt {
  private static final Logger LOGGER = LoggerFactory.getLogger("test");
  private static final Font font = new Font("微软雅黑", Font.BOLD, 20);
  public static void main(String[] args) {
  }
  @SuppressWarnings("unused")
  private static void configLog(String configFile) {
    if (new File(configFile).exists()) {
      PropertyConfigurator.configure(configFile);
      return;
    }
    Properties properties = new Properties();
    properties.setProperty("log4j.rootLogger", "DEBUG, CA");
    properties.setProperty("log4j.appender.CA", "org.apache.log4j.ConsoleAppender");
    properties.setProperty("log4j.appender.CA.layout", "org.apache.log4j.PatternLayout");
    properties.setProperty("log4j.appender.CA.layout.ConversionPattern", "%d{yyyy-MM-dd HH:mm:ss.SSS} %-4r [%t] %-5p %c %x - %m%n");
    PropertyConfigurator.configure(properties);
  }
  public static void generateQRCode(QArtEntity qArtEntity) {
    if (null != qArtEntity.get_help()) {
      if (qArtEntity.get_help().equals("?") || qArtEntity.get_help().equals("help")) {
        //TODO
      }
    }
    //String log4j = qArtEntity.getLog4j();
    // input
    String filename = qArtEntity.getInput();
    String url = qArtEntity.getUrl();
    // QR code
    int version = qArtEntity.getVersion();
    int mask = qArtEntity.getMask();
    int quietZone = qArtEntity.getQuietZone();
    int rotation = qArtEntity.getRotation();
    int size = qArtEntity.getSize();
    int colorBlack = qArtEntity.getColorBlack();
    int colorWhite = qArtEntity.getColorWhite();
    // how to generate QR code
    boolean randControl = qArtEntity.isRandControl();
    long seed = qArtEntity.getSeed();
    if (seed == -1) {
      seed = System.currentTimeMillis();
    }
    boolean dither = qArtEntity.isDither();
    boolean onlyDataBits = qArtEntity.isOnlyData();
    boolean saveControl = qArtEntity.isSaveControl();
    // output image
    int width = qArtEntity.getWidth();
    int height = qArtEntity.getHeight();
    Integer marginTop = qArtEntity.getMarginTop();
    Integer marginBottom = qArtEntity.getMarginBottom();
    Integer marginLeft = qArtEntity.getMarginLeft();
    Integer marginRight = qArtEntity.getMarginRight();
    String outputFormat = qArtEntity.getOutputFormat();
    String output = qArtEntity.getOutput();
    // todo validate input params, make sure all of them are valid
    try {
      BufferedImage input = ImageUtil.loadImage(filename, width, height);
      int qrSizeWithoutQuiet = 17 + 4 * version;
      int qrSize = qrSizeWithoutQuiet + quietZone * 2;
      if (size < qrSize) { // don't scale
        size = qrSize;
      }
      int scale = size / qrSize;
      int targetQrSizeWithoutQuiet = qrSizeWithoutQuiet * scale;
      Rectangle inputImageRect = new Rectangle(new Point(0, 0), width, height);
      int startX = 0, startY = 0;
      if (marginLeft != null) {
        startX = marginLeft;
      }
      else if (marginRight != null) {
        startX = width - marginRight - size;
      }
      if (marginTop != null) {
        startY = marginTop;
      }
      else if (marginBottom != null) {
        startY = height - marginBottom - size;
      }
      Rectangle qrRect = new Rectangle(new Point(startX, startY), size, size);
      Rectangle qrWithoutQuietRect = new Rectangle(new Point(startX + (size - targetQrSizeWithoutQuiet) / 2, startY + (size - targetQrSizeWithoutQuiet) / 2), targetQrSizeWithoutQuiet, targetQrSizeWithoutQuiet);
      int[][] target = null;
      int dx = 0, dy = 0;
      BufferedImage targetImage = null;
      Rectangle targetRect = inputImageRect.intersect(qrWithoutQuietRect);
      if (targetRect == null) {
        LOGGER.warn("no intersect zone");
        target = new int[0][0];
      }
      else {
        targetImage = input.getSubimage(targetRect.start.x, targetRect.start.y, targetRect.width, targetRect.height);
        int scaledWidth = targetRect.width / scale;
        int scaledHeight = targetRect.height / scale;
        BufferedImage scaledImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics graphics = scaledImage.createGraphics();
        graphics.drawImage(targetImage, 0, 0, scaledWidth, scaledHeight, null);
        graphics.dispose();
        target = ImageUtil.makeTarget(scaledImage, 0, 0, scaledWidth, scaledHeight);
        dx = (qrWithoutQuietRect.start.x - targetRect.start.x) / scale;
        dy = (qrWithoutQuietRect.start.y - targetRect.start.y) / scale;
      }
      cn.zch.soft.util.qrcode.utils.qartutil.Image image = new Image(target, dx, dy, url, version, mask, rotation, randControl, seed, dither, onlyDataBits, saveControl);
      QRCode qrCode = image.encode();
      BitMatrix bitMatrix = ImageUtil.makeBitMatrix(qrCode, quietZone, size);
      MatrixToImageConfig config = new MatrixToImageConfig(colorBlack, colorWhite);
      BufferedImage finalQrImage = MatrixToImageWriter.toBufferedImage(bitMatrix, config);
      Rectangle finalRect = qrRect.union(inputImageRect);
      BufferedImage finalImage = new BufferedImage(finalRect.width, finalRect.height, BufferedImage.TYPE_INT_RGB);
      Graphics graphics = finalImage.createGraphics();
      graphics.drawImage(input, inputImageRect.start.x - finalRect.start.x, inputImageRect.start.y - finalRect.start.y, inputImageRect.width, inputImageRect.height, null);
      graphics.drawImage(finalQrImage, qrRect.start.x - finalRect.start.x, qrRect.start.y - finalRect.start.y, qrRect.width, qrRect.height, null);
      graphics.setFont(font);
      graphics.drawString("zch.", qrRect.start.x - finalRect.start.x, qrRect.start.y - finalRect.start.y);
      graphics.dispose();
      if (outputFormat.toUpperCase().contentEquals("JPEG")) {
        // Creating a non Alpha channel bufferedImage so that alpha channel does not corrupt jpeg.
        BufferedImage nonAlpha = new BufferedImage(finalImage.getWidth(), finalImage.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics nonAlphaGraphics = nonAlpha.createGraphics();
        nonAlphaGraphics.setColor(Color.white);
        nonAlphaGraphics.fillRect(0, 0, finalImage.getWidth(), finalImage.getHeight());
        nonAlphaGraphics.drawImage(finalImage, 0, 0, null);
        nonAlphaGraphics.dispose();
        finalImage = nonAlpha;
      }
      ImageIO.write(finalImage, outputFormat, new File(output));
    }
    catch (Exception e) {
      LOGGER.error("encode error", e);
    }
  }
}
